home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / dev / lang / Python16_Src.lha / Python16_Source / Python / thread_pth.h < prev    next >
Encoding:
C/C++ Source or Header  |  2000-08-03  |  7.4 KB  |  298 lines

  1. /* GNU pth threads interface
  2.    http://www.gnu.org/software/pth
  3.    2000-05-03 Andy Dustman <andy@dustman.net>
  4.  
  5.    Adapted from Posix threads interface 
  6.    12 May 1997 -- david arnold <davida@pobox.com>
  7.  */
  8.  
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <pth.h>
  12.  
  13. /* A pth mutex isn't sufficient to model the Python lock type
  14.  * because pth mutexes can be acquired multiple times by the
  15.  * same thread.
  16.  *
  17.  * The pth_lock struct implements a Python lock as a "locked?" bit
  18.  * and a <condition, mutex> pair.  In general, if the bit can be acquired
  19.  * instantly, it is, else the pair is used to block the thread until the
  20.  * bit is cleared.
  21.  */
  22.  
  23. typedef struct {
  24.     char             locked; /* 0=unlocked, 1=locked */
  25.     /* a <cond, mutex> pair to handle an acquire of a locked lock */
  26.     pth_cond_t   lock_released;
  27.     pth_mutex_t  mut;
  28. } pth_lock;
  29.  
  30. #define CHECK_STATUS(name)  if (status == -1) { printf("%d ", status); perror(name); error = 1; }
  31.  
  32. /*
  33.  * Initialization.
  34.  */
  35.  
  36. static void PyThread__init_thread _P0()
  37. {
  38.     pth_init();
  39. }
  40.  
  41. /*
  42.  * Thread support.
  43.  */
  44.  
  45.  
  46. int PyThread_start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg)
  47. {
  48.     pth_t th;
  49.     int success;
  50.     dprintf(("PyThread_start_new_thread called\n"));
  51.     if (!initialized)
  52.         PyThread_init_thread();
  53.  
  54.     th = pth_spawn(PTH_ATTR_DEFAULT,
  55.                  (void* (*)_P((void *)))func,
  56.                  (void *)arg
  57.                  );
  58.  
  59.     return th == NULL ? 0 : 1;
  60. }
  61.  
  62. long PyThread_get_thread_ident _P0()
  63. {
  64.     volatile pth_t threadid;
  65.     if (!initialized)
  66.         PyThread_init_thread();
  67.     /* Jump through some hoops for Alpha OSF/1 */
  68.     threadid = pth_self();
  69.     return (long) *(long *) &threadid;
  70. }
  71.  
  72. static void do_PyThread_exit_thread _P1(no_cleanup, int no_cleanup)
  73. {
  74.     dprintf(("PyThread_exit_thread called\n"));
  75.     if (!initialized) {
  76.         if (no_cleanup)
  77.             _exit(0);
  78.         else
  79.             exit(0);
  80.     }
  81. }
  82.  
  83. void PyThread_exit_thread _P0()
  84. {
  85.     do_PyThread_exit_thread(0);
  86. }
  87.  
  88. void PyThread__exit_thread _P0()
  89. {
  90.     do_PyThread_exit_thread(1);
  91. }
  92.  
  93. #ifndef NO_EXIT_PROG
  94. static void do_PyThread_exit_prog _P2(status, int status, no_cleanup, int no_cleanup)
  95. {
  96.     dprintf(("PyThread_exit_prog(%d) called\n", status));
  97.     if (!initialized)
  98.         if (no_cleanup)
  99.             _exit(status);
  100.         else
  101.             exit(status);
  102. }
  103.  
  104. void PyThread_exit_prog _P1(status, int status)
  105. {
  106.     do_PyThread_exit_prog(status, 0);
  107. }
  108.  
  109. void PyThread__exit_prog _P1(status, int status)
  110. {
  111.     do_PyThread_exit_prog(status, 1);
  112. }
  113. #endif /* NO_EXIT_PROG */
  114.  
  115. /*
  116.  * Lock support.
  117.  */
  118. PyThread_type_lock PyThread_allocate_lock _P0()
  119. {
  120.     pth_lock *lock;
  121.     int status, error = 0;
  122.  
  123.     dprintf(("PyThread_allocate_lock called\n"));
  124.     if (!initialized)
  125.         PyThread_init_thread();
  126.  
  127.     lock = (pth_lock *) malloc(sizeof(pth_lock));
  128.         memset((void *)lock, '\0', sizeof(pth_lock));
  129.     if (lock) {
  130.         lock->locked = 0;
  131.         status = pth_mutex_init(&lock->mut);
  132.         CHECK_STATUS("pth_mutex_init");
  133.         status = pth_cond_init(&lock->lock_released);
  134.         CHECK_STATUS("pth_cond_init");
  135.         if (error) {
  136.             free((void *)lock);
  137.             lock = NULL;
  138.         }
  139.     }
  140.     dprintf(("PyThread_allocate_lock() -> %lx\n", (long)lock));
  141.     return (PyThread_type_lock) lock;
  142. }
  143.  
  144. void PyThread_free_lock _P1(lock, PyThread_type_lock lock)
  145. {
  146.     pth_lock *thelock = (pth_lock *)lock;
  147.     int status, error = 0;
  148.  
  149.     dprintf(("PyThread_free_lock(%lx) called\n", (long)lock));
  150.  
  151.     free((void *)thelock);
  152. }
  153.  
  154. int PyThread_acquire_lock _P2(lock, PyThread_type_lock lock, waitflag, int waitflag)
  155. {
  156.     int success;
  157.     pth_lock *thelock = (pth_lock *)lock;
  158.     int status, error = 0;
  159.  
  160.     dprintf(("PyThread_acquire_lock(%lx, %d) called\n", (long)lock, waitflag));
  161.  
  162.     status = pth_mutex_acquire(&thelock->mut, !waitflag, NULL);
  163.     CHECK_STATUS("pth_mutex_acquire[1]");
  164.     success = thelock->locked == 0;
  165.         if (success) thelock->locked = 1;
  166.         status = pth_mutex_release( &thelock->mut );
  167.         CHECK_STATUS("pth_mutex_release[1]");
  168.  
  169.         if ( !success && waitflag ) {
  170.                 /* continue trying until we get the lock */
  171.  
  172.                 /* mut must be locked by me -- part of the condition
  173.                  * protocol */
  174.                 status = pth_mutex_acquire( &thelock->mut, !waitflag, NULL );
  175.                 CHECK_STATUS("pth_mutex_acquire[2]");
  176.                 while ( thelock->locked ) {
  177.                         status = pth_cond_await(&thelock->lock_released,
  178.                                                 &thelock->mut, NULL);
  179.                         CHECK_STATUS("pth_cond_await");
  180.                 }
  181.                 thelock->locked = 1;
  182.                 status = pth_mutex_release( &thelock->mut );
  183.                 CHECK_STATUS("pth_mutex_release[2]");
  184.                 success = 1;
  185.         }
  186.         if (error) success = 0;
  187.         dprintf(("PyThread_acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success));
  188.     return success;
  189. }
  190.  
  191. void PyThread_release_lock _P1(lock, PyThread_type_lock lock)
  192. {
  193.         pth_lock *thelock = (pth_lock *)lock;
  194.         int status, error = 0;
  195.  
  196.         dprintf(("PyThread_release_lock(%lx) called\n", (long)lock));
  197.  
  198.         status = pth_mutex_acquire( &thelock->mut, 0, NULL );
  199.         CHECK_STATUS("pth_mutex_acquire[3]");
  200.  
  201.         thelock->locked = 0;
  202.  
  203.         status = pth_mutex_release( &thelock->mut );
  204.         CHECK_STATUS("pth_mutex_release[3]");
  205.  
  206.         /* wake up someone (anyone, if any) waiting on the lock */
  207.         status = pth_cond_notify( &thelock->lock_released, 0 );
  208.         CHECK_STATUS("pth_cond_notify");
  209. }
  210.  
  211. /*
  212.  * Semaphore support.
  213.  */
  214.  
  215. struct semaphore {
  216.     pth_mutex_t mutex;
  217.     pth_cond_t cond;
  218.     int value;
  219. };
  220.  
  221. PyThread_type_sema PyThread_allocate_sema _P1(value, int value)
  222. {
  223.     struct semaphore *sema;
  224.     int status, error = 0;
  225.  
  226.     dprintf(("PyThread_allocate_sema called\n"));
  227.     if (!initialized)
  228.         PyThread_init_thread();
  229.  
  230.     sema = (struct semaphore *) malloc(sizeof(struct semaphore));
  231.     if (sema != NULL) {
  232.         sema->value = value;
  233.         status = pth_mutex_init(&sema->mutex);
  234.         CHECK_STATUS("pth_mutex_init");
  235.         status = pth_cond_init(&sema->cond);
  236.         CHECK_STATUS("pth_mutex_init");
  237.         if (error) {
  238.             free((void *) sema);
  239.             sema = NULL;
  240.         }
  241.     }
  242.     dprintf(("PyThread_allocate_sema() -> %lx\n", (long) sema));
  243.     return (PyThread_type_sema) sema;
  244. }
  245.  
  246. void PyThread_free_sema _P1(sema, PyThread_type_sema sema)
  247. {
  248.     int status, error = 0;
  249.     struct semaphore *thesema = (struct semaphore *) sema;
  250.  
  251.     dprintf(("PyThread_free_sema(%lx) called\n", (long) sema));
  252.     free((void *) thesema);
  253. }
  254.  
  255. int PyThread_down_sema _P2(sema, PyThread_type_sema sema, waitflag, int waitflag)
  256. {
  257.     int status, error = 0, success;
  258.     struct semaphore *thesema = (struct semaphore *) sema;
  259.  
  260.     dprintf(("PyThread_down_sema(%lx, %d) called\n", (long) sema, waitflag));
  261.     status = pth_mutex_acquire(&thesema->mutex, !waitflag, NULL);
  262.     CHECK_STATUS("pth_mutex_acquire");
  263.     if (waitflag) {
  264.         while (!error && thesema->value <= 0) {
  265.             status = pth_cond_await(&thesema->cond,
  266.                         &thesema->mutex, NULL);
  267.             CHECK_STATUS("pth_cond_await");
  268.         }
  269.     }
  270.     if (error)
  271.         success = 0;
  272.     else if (thesema->value > 0) {
  273.         thesema->value--;
  274.         success = 1;
  275.     }
  276.     else
  277.         success = 0;
  278.     status = pth_mutex_release(&thesema->mutex);
  279.     CHECK_STATUS("pth_mutex_release");
  280.     dprintf(("PyThread_down_sema(%lx) return\n", (long) sema));
  281.     return success;
  282. }
  283.  
  284. void PyThread_up_sema _P1(sema, PyThread_type_sema sema)
  285. {
  286.     int status, error = 0;
  287.     struct semaphore *thesema = (struct semaphore *) sema;
  288.  
  289.     dprintf(("PyThread_up_sema(%lx)\n", (long) sema));
  290.     status = pth_mutex_acquire(&thesema->mutex, 0, NULL);
  291.     CHECK_STATUS("pth_mutex_acquire");
  292.     thesema->value++;
  293.     status = pth_cond_notify(&thesema->cond, 1);
  294.     CHECK_STATUS("pth_cond_notify");
  295.     status = pth_mutex_release(&thesema->mutex);
  296.     CHECK_STATUS("pth_mutex_release");
  297. }
  298.